package util

import (
	"encoding/json"
	"fmt"
)

type MysqlRow map[string]any

func NewMysqlRow() *MysqlRow {
	row := make(MysqlRow)
	return &row
}

func NewMysqlRowFrom(x any) (*MysqlRow, error) {
	if x == nil {
		return nil, fmt.Errorf("obj is nil")
	}
	bs, err := json.Marshal(x)
	if err != nil {
		return nil, err
	}
	var row MysqlRow
	err = json.Unmarshal(bs, &row)
	if err != nil {
		return nil, err
	}
	if (&row).IsEmpty() {
		return nil, fmt.Errorf("obj is empty")
	}
	return &row, nil
}

func (row *MysqlRow) Get(key string) any {
	if row.IsEmpty() {
		return nil
	}
	return (*row)[key]
}

func (row *MysqlRow) ToStr(key string) string {
	return AnyToStr(row.Get(key))
}

func (row *MysqlRow) IsEmpty() bool {
	return row == nil || *row == nil || len(*row) == 0
}

func (row *MysqlRow) ToStrings(key string) []string {
	a := row.Get(key)
	s := AnyToStr(a)
	ret, ok := a.([]string)
	if !ok {
		_ = json.Unmarshal([]byte(s), &ret)
	}
	if len(ret) == 0 {
		ret = []string{s}
	}
	return ret
}

func (row *MysqlRow) ToMap(key string) map[string]any {
	ret, ok := row.Get(key).(map[string]any)
	if !ok {
		_ = json.Unmarshal([]byte(row.ToStr(key)), &ret)
	}
	return ret
}

func (row *MysqlRow) ToBool(key string) bool {
	return AnyToBool(row.Get(key))
}

func (row *MysqlRow) ToInt64(key string) int64 {
	return AnyToInt64(row.Get(key))
}

func (row *MysqlRow) ToNum(key string) float64 {
	return AnyToFloat64(row.Get(key))
}

func (row *MysqlRow) Drop(keys ...string) {
	if row.IsEmpty() {
		return
	}
	for _, key := range keys {
		delete(*row, key)
	}
}

func (row *MysqlRow) DropAll() {
	if row.IsEmpty() {
		return
	}
	clear(*row)
}

func (row *MysqlRow) Set(key string, val any) {
	if row == nil || *row == nil {
		return
	}
	(*row)[key] = val
}

func (row *MysqlRow) Has(key string) bool {
	if row.IsEmpty() {
		return false
	}
	_, ok := (*row)[key]
	return ok
}
